﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using StyleCop;
using Microsoft.Win32;

namespace ReadSolutionContents
{
    class Scanner
    {
        static List<Violations> violationsList = new List<Violations>();

        int violationCount;

        public string[] Filelist { get; set; }

        private string settingsfile = string.Empty;

        public string SettingsFile
        {
            get
            {
                if (string.IsNullOrEmpty(settingsfile))
                {
                    settingsfile = Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\CodePlex\StyleCop", "InstallDir", string.Empty).ToString();

                    if (string.IsNullOrEmpty(settingsfile))
                    {
                        settingsfile = Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\CodePlex\StyleCop", "InstallLocation", string.Empty).ToString();
                    }
                    if (string.IsNullOrEmpty(settingsfile))
                    {
                        settingsfile = AppDomain.CurrentDomain.BaseDirectory;
                    }

                    settingsfile += @"\Settings.StyleCop";
                }

                return settingsfile;
            }
            set
            {
                settingsfile = value;
            }
        }

        private string violationfile = string.Empty;

        public string ViolationFile
        {
            get
            {
                if (string.IsNullOrEmpty(violationfile))
                {
                    violationfile = AppDomain.CurrentDomain.BaseDirectory + "\\Violations.XML";
                }

                return violationfile;
            }
            set
            {
                violationfile = value;
            }
        }

        public string Location { get; set; }

        void AddViolation(string file, string ID, string Message, string line, string column)
        {
            violationsList.Add(new Violations(file, ID, Message, line, column));
        }

        void validate(bool multiple = false)
        {
            if (!System.IO.File.Exists(this.SettingsFile))
            {
                throw new System.IO.FileNotFoundException("Settings File Was not Found");
            }

            if (!System.IO.Directory.Exists(this.Location))
            {
                throw new System.IO.DirectoryNotFoundException("Project Location directory not found");
            }

            if (multiple == false && !(this.Filelist.Count() >= 1))
            {
                throw new System.ArgumentException("File list is empty");
            }
        }

        public void ScanProject()
        {
            validate();

            StyleCopConsole console = new StyleCopConsole(SettingsFile, true, ViolationFile, null, true);
            Configuration configuration = new Configuration(new string[] { "DEBUG" });
            CodeProject project = new CodeProject(0, Location, configuration);

            foreach (var file in this.Filelist)
            {
                console.Core.Environment.AddSourceCode(project, file, null);
            }

            console.OutputGenerated += console_OutputGenerated;
            console.ViolationEncountered += console_ViolationEncountered;
            console.Start(new CodeProject[] { project }, true);
        }

        public void ScanMultipleProjects(string[] projects, string[][] filelist)
        {
            if (projects.Length != filelist.Length)
            {
                throw new Exception("Number of projects and file list is not same");
            }

            StyleCopConsole console = new StyleCopConsole(SettingsFile, true, ViolationFile, null, true);
            Configuration configuration = new Configuration(new string[] { "DEBUG" });
            CodeProject[] project = new CodeProject[projects.Length];
            //new CodeProject(0, Location, configuration);

            for (int i = 0; i < projects.Count(); i++)
            {
                System.IO.FileInfo p = new System.IO.FileInfo(projects[i]);
                string Locationtemp = p.DirectoryName;

                project[i] = new CodeProject(i, Locationtemp, configuration);

                for (int j = 0; j < filelist[i].Count(); j++)
                {
                    console.Core.Environment.AddSourceCode(project[i], filelist[i][j], null);
                }
            }

            //foreach (var file in this.Filelist)
            //{
            //    console.Core.Environment.AddSourceCode(project, file, null);
            //}

            console.OutputGenerated += console_OutputGenerated;
            console.ViolationEncountered += console_ViolationEncountered;
            console.Start(project, true);
        }

        public void start()
        {
            //StyleCopConsole console = new StyleCopConsole("c:\\", true, null, null, true);
            //   CodeProject prj = new CodeProject(0, "", null);
            string file = @"C:\Users\mehuladmin\Documents\Visual Studio 2012\Projects\ReadSolutionContents\ReadSolutionContents\Program.cs";
            string settingsfile = @"C:\Users\mehuladmin\Documents\Visual Studio 2012\Projects\ReadSolutionContents\ReadSolutionContents\bin\Debug\backup_Settings.StyleCop";
            string violationfile = @"C:\Users\mehuladmin\Documents\Visual Studio 2012\Projects\ReadSolutionContents\ReadSolutionContents\bin\Debug\MyViolations.xml";
            StyleCopConsole console = new StyleCopConsole(settingsfile, true, violationfile, null, true);

            Configuration configuration = new Configuration(new string[] { "DEBUG" });
            string evalpath = @"C:\Users\mehuladmin\Documents\Visual Studio 2012\Projects\ReadSolutionContents\ReadSolutionContents\";
            string file1 = @"C:\Users\mehuladmin\Documents\Visual Studio 2012\Projects\ReadSolutionContents\ReadSolutionContents\Scanner.cs";
            string file2 = @"C:\Users\mehuladmin\Documents\Visual Studio 2012\Projects\ReadSolutionContents\ReadSolutionContents\RegUtil\RegisteryUtil.cs";
            CodeProject project = new CodeProject(0, evalpath, configuration);
            console.Core.Environment.AddSourceCode(project, file, null);
            console.Core.Environment.AddSourceCode(project, file1, null);
            console.Core.Environment.AddSourceCode(project, file2, null);
            console.OutputGenerated += console_OutputGenerated;
            console.ViolationEncountered += console_ViolationEncountered;
            console.Start(new CodeProject[] { project }, true);
        }

        public delegate void InfoEvent(object sender, string message);

        public event InfoEvent Info;

        void console_OutputGenerated(object sender, OutputEventArgs args)
        {
            if (Info != null)
            {
                Info.Invoke(sender, args.Output);
            }

            Console.WriteLine(args.Output);
        }

        void console_ViolationEncountered(object sender, ViolationEventArgs e)
        {
            Param.Ignore(sender);
            Param.AssertNotNull(e, "e");

            this.violationCount++;


            string path = string.Empty;
            if (e.SourceCode != null && e.SourceCode.Path != null && e.SourceCode.Path.Length > 0)
            {
                path = e.SourceCode.Path;
            }
            else if (e.Element != null && e.Element.Document != null && e.Element.Document.SourceCode != null && e.Element.Document.SourceCode.Path != null)
            {
                path = e.Element.Document.SourceCode.Path;
            }

            lock (this)
            {
                string trimmedNamespace = e.Violation.Rule.Namespace.SubstringAfter(StyleCop.Constants.ProductName + ".", StringComparison.Ordinal);
                trimmedNamespace = trimmedNamespace.SubstringBeforeLast("Rules", StringComparison.Ordinal);

                string description = string.Concat(e.Violation.Rule.CheckId, " : ", trimmedNamespace, " : ", e.Message);

                if (e.Location != null)
                {
                    AddViolation(path, e.Violation.Rule.CheckId, trimmedNamespace + " : " + e.Message, e.Location.StartPoint.LineNumber.ToString(), e.Location.StartPoint.IndexOnLine.ToString());
                }
                else
                {
                    AddViolation(path, e.Violation.Rule.CheckId, trimmedNamespace + " : " + e.Message, e.LineNumber.ToString(), "0");
                }
            }
        }

    }
}